package com.fary.beans;

import com.fary.core.SpringException;
import jdk.internal.jline.internal.Nullable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public abstract class AbstractPropertyAccessor extends TypeConverterSupport implements ConfigurablePropertyAccessor {

    private boolean extractOldValueForEditor = false;

    private boolean autoGrowNestedPaths = false;


    @Override
    public void setExtractOldValueForEditor(boolean extractOldValueForEditor) {
        this.extractOldValueForEditor = extractOldValueForEditor;
    }

    @Override
    public boolean isExtractOldValueForEditor() {
        return this.extractOldValueForEditor;
    }

    @Override
    public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
        this.autoGrowNestedPaths = autoGrowNestedPaths;
    }

    @Override
    public boolean isAutoGrowNestedPaths() {
        return this.autoGrowNestedPaths;
    }


    @Override
    public void setPropertyValue(PropertyValue pv) throws SpringException {
        setPropertyValue(pv.getName(), pv.getValue());
    }

    @Override
    public void setPropertyValues(Map<?, ?> map) throws SpringException {
        setPropertyValues(new MutablePropertyValues(map));
    }

    @Override
    public void setPropertyValues(PropertyValues pvs) throws SpringException {
        setPropertyValues(pvs, false, false);
    }

    @Override
    public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws SpringException {
        setPropertyValues(pvs, ignoreUnknown, false);
    }

    @Override
    public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws SpringException {

        List<SpringException> propertyAccessExceptions = null;
        PropertyValue[] propertyValues = pvs.getPropertyValues();
        for (PropertyValue pv : propertyValues) {
            try {
                setPropertyValue(pv);
            } catch (SpringException ex) {
                if (!ignoreUnknown || !ignoreInvalid) {
                    throw ex;
                }
                if (propertyAccessExceptions == null) {
                    propertyAccessExceptions = new ArrayList<>();
                }
                propertyAccessExceptions.add(ex);
            }
        }
    }


    // Redefined with public visibility.
    @Override
    public Class<?> getPropertyType(String propertyPath) {
        return null;
    }

    /**
     * Actually get the value of a property.
     */
    @Override
    public abstract Object getPropertyValue(String propertyName) throws SpringException;

    /**
     * Actually set a property value.
     */
    @Override
    public abstract void setPropertyValue(String propertyName, Object value) throws SpringException;

}